package com.zmn.plat.services.impl.company;

import com.alibaba.dubbo.config.annotation.Reference;
import com.zmn.common.constant.GlobalConsts;
import com.zmn.common.dictionary.DictModel;
import com.zmn.common.dto.StatusDTO;
import com.zmn.common.utils.collection.CollectionUtil;
import com.zmn.common.utils.date.DateUtil;
import com.zmn.common.utils.number.NumberUtil;
import com.zmn.mcc.common.constant.DpermitConsts;
import com.zmn.mcc.common.dto.permit.SpermitDTO;
import com.zmn.mcc.dubbo.dto.DubboConsts;
import com.zmn.mcc.dubbo.interfaces.staff.StaffPermitRemoteService;
import com.zmn.mcc.permit.mysql.annotation.ZmnDPermit;
import com.zmn.mcc.permit.mysql.enums.DPermitTypeEnum;
import com.zmn.plat.common.constant.CompanyConsts;
import com.zmn.plat.model.entity.company.BaseCompany;
import com.zmn.plat.model.entity.company.BaseCompanyQuery;
import com.zmn.plat.model.entity.company.BaseCompanyTarget;
import com.zmn.plat.model.entity.company.CompanyTypeQuery;
import com.zmn.plat.model.vo.company.BaseCompanyVO;
import com.zmn.plat.persistence.interfaces.company.CompanyDao;
import com.zmn.plat.persistence.interfaces.company.CompanyTargetDao;
import com.zmn.plat.services.interfaces.company.BaseCompanyService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.*;

/**
 * @author duanzuocai
 * @version v1.0
 * @类说明：公司服务
 * @since 2018/10/16 11:29
 */
@Service
@Slf4j
public class BaseCompanyServiceImpl implements BaseCompanyService {
    @Resource
    CompanyDao companyDao;
    @Resource
    CompanyTargetDao companyTargetDao;
    @Reference(version = DubboConsts.INTERFACE_VERSION, check = false)
    StaffPermitRemoteService staffPermitRemoteService;

    @Override
    public BaseCompanyVO findByKey(Integer companyId) {
        return companyDao.findByKey(companyId);
    }

    @Override
    public BaseCompany findOneByPlat(Integer plat) {
        return companyDao.findOneByPlat(plat);
    }

    @Override
    public BaseCompany findByName(String name) {
        return companyDao.findByName(name);
    }

    @Override
    public BaseCompany findByFullName(String fullName) {
        return companyDao.findByFullName(fullName);
    }

    @Override
    public List<BaseCompany> findByKeys(List<Integer> ids, Integer type, Integer childType, Integer status) {
        return companyDao.findByKeys(ids, type, childType, status);
    }

    @Override
    public List<BaseCompany> findByKeysAndTypes(List<Integer> ids, List<CompanyTypeQuery> companyTypeQueryList, Integer status, Integer plat) {
        return companyDao.findByKeysAndTypes(ids, companyTypeQueryList, status, plat);
    }

    @Override
    public Integer findZmnCompanyId() {
        return GlobalConsts.ZMN_COMPANY_ID;
    }

    @Override
    public List<BaseCompanyVO> listPageByQuery(BaseCompanyQuery query, Integer staffId) {

        /**
         * 如果有员工ID，走权限信息 规则：如果有公司类型，根据类型走不同的数据权限 如果没有公司类型，有公司类型集合，根据集合的第一条数据当成公司类型做数据权限 如果没有类型相关数据，则根据其他条件查询出公司信息，根据集合的第一条数据做数据权限
         */
        if (NumberUtil.isPositiveInteger(staffId)) {
            query.setOperatorId(staffId);
            return listPageByQueryOfPermit(query);
        }

        int count = countByQuery(query);
        query.setTotalCount(count);

        return companyDao.listPageByQuery(query);
    }

    @ZmnDPermit(types = {DPermitTypeEnum.ORG_ONE})
    public List<BaseCompanyVO> listPageByQueryOfPermitPlat(BaseCompanyQuery query) {
        int count = countByQueryOfPermitPlat(query);
        query.setTotalCount(count);

        return companyDao.listPageByQuery(query);
    }

    @ZmnDPermit(types = {DPermitTypeEnum.ORG_TWO})
    public List<BaseCompanyVO> listPageByQueryOfPermitRegion(BaseCompanyQuery query) {
        int count = countByQueryOfPermitRegion(query);
        query.setTotalCount(count);

        return companyDao.listPageByQuery(query);
    }

    @ZmnDPermit(types = {DPermitTypeEnum.ORG_THR})
    public List<BaseCompanyVO> listPageByQueryOfPermitSub(BaseCompanyQuery query) {
        int count = countByQueryOfPermitSub(query);
        query.setTotalCount(count);

        return companyDao.listPageByQuery(query);
    }

    @ZmnDPermit(types = {DPermitTypeEnum.COMP_SP})
    public List<BaseCompanyVO> listPageByQueryOfPermitGrandson(BaseCompanyQuery query) {
        int count = countByQueryOfPermitGrandson(query);
        query.setTotalCount(count);

        return companyDao.listPageByQuery(query);
    }

    @Override
    public List<BaseCompanyVO> listPageByQueryOfPermit(BaseCompanyQuery query) {
        List<BaseCompanyVO> baseCompanyVOList = Collections.emptyList();

        // 默认服务商
        Integer type;
        if (Objects.nonNull(query.getType())) {
            type = query.getType();
        } else if (CollectionUtil.isNotNullOrEmpty(query.getCompanyTypeQueryList())) {
            type = query.getCompanyTypeQueryList().get(0).getType();
        } else {
            BaseCompany baseCompany = companyDao.findFristByQuery(query);
            if (Objects.isNull(baseCompany)) {
                return baseCompanyVOList;
            }

            type = baseCompany.getType();
        }

        if (NumberUtil.isNullOrZero(type)) {
            return baseCompanyVOList;
        }

        SpermitDTO spermitDTO = staffPermitRemoteService.listDpermitByStaffId(query.getOperatorId(), DpermitConsts.TYPE_ORGANIZE, true);
        if (spermitDTO.isSuccess() && Objects.equals(spermitDTO.getRange(), SpermitDTO.RANGE_ALL)) {
            query.setOperatorId(0);
            return listPageByQuery(query, null);
        }

        // 权限接口有误，走正常逻辑
        if (!spermitDTO.isSuccess() && Objects.isNull(spermitDTO.getLevel())) {
            query.setOperatorId(0);
            return listPageByQuery(query, null);
        }

        int permitLevel = spermitDTO.getLevel();

        // 根据不同类型调用不同类型数据权限的公司：总部
        if (Objects.equals(type, CompanyConsts.COMPANY_TYPE_HEADOFFICE) || Objects.equals(permitLevel, DpermitConsts.ORGANIZE_LEVEL_PLAT)) {
            return listPageByQueryOfPermitPlat(query);
        }

        // 根据不同类型调用不同类型数据权限的公司：大区
        if (Objects.equals(type, CompanyConsts.COMPANY_TYPE_REGION) || Objects.equals(permitLevel, DpermitConsts.ORGANIZE_LEVEL_REGION)) {
            return listPageByQueryOfPermitRegion(query);
        }

        // 根据不同类型调用不同类型数据权限的公司 ：子公司
        if (Objects.equals(type, CompanyConsts.COMPANY_TYPE_SUBSIDIARY) || Objects.equals(permitLevel, DpermitConsts.ORGANIZE_LEVEL_SUB)) {
            return listPageByQueryOfPermitSub(query);
        }

        // 根据不同类型调用不同类型数据权限的公司 ：服务商
        if (Objects.equals(type, CompanyConsts.COMPANY_TYPE_SERVICE) || Objects.equals(permitLevel, DpermitConsts.ORGANIZE_LEVEL_GRANDSON)) {
            return listPageByQueryOfPermitGrandson(query);
        }

        // 其他公司类型，不支持数据权限
        query.setOperatorId(0);
        return listPageByQuery(query, null);
    }

    @Override
    public List<BaseCompany> listByQuery(BaseCompanyQuery query) {
        return companyDao.listByQuery(query);
    }

    @Override
    public List<BaseCompanyVO> listVOByQuery(BaseCompanyQuery query) {
        return companyDao.listVOByQuery(query);
    }

    @Override
    public List<DictModel> listAll() {
        List<BaseCompany> list = listByQuery(new BaseCompanyQuery());
        List<DictModel> models = new ArrayList<>(list.size());
        list.forEach(company -> {
            models.add(new DictModel(company.getCompanyId(), company.getName()));
        });
        return models;
    }

    @Override
    public List<DictModel> listByTypes(List<CompanyTypeQuery> companyTypeQueryList, Integer plat) {
        List<BaseCompany> list = companyDao.findByKeysAndTypes(null, companyTypeQueryList, null, plat);
        List<DictModel> models = new ArrayList<>();
        if (list != null) {
            list.forEach(company -> {
                models.add(new DictModel(company.getCompanyId(), company.getName()));
            });
        }
        return models;
    }

    @Override
    public List<DictModel> listByTypesAndStatus(List<CompanyTypeQuery> companyTypeQueryList, Integer status, Integer plat) {
        BaseCompanyQuery companyQuery = new BaseCompanyQuery();
        if (!CollectionUtils.isEmpty(companyTypeQueryList)) {
            companyQuery.setCompanyTypeQueryList(companyTypeQueryList);
        }
        if (NumberUtil.isPositiveInteger(status)) {
            companyQuery.setStatus(status);
        }
        if (NumberUtil.isPositiveInteger(plat)) {
            companyQuery.setPlat(plat);
        }
        List<BaseCompany> list = companyDao.listByQuery(companyQuery);
        List<DictModel> models = new ArrayList<>();
        if (list != null) {
            list.forEach(company -> {
                models.add(new DictModel(company.getCompanyId(), company.getName()));
            });
        }
        return models;
    }

    @Override
    public List<BaseCompany> listByOrganIds(List<Integer> orgIds) {
        return listByOrganIds(orgIds, null, null);
    }

    @Override
    public List<BaseCompany> listByOrganIds(List<Integer> orgIds, Integer type, Integer childType) {
        if (orgIds == null || orgIds.size() == 0) {
            return Collections.emptyList();
        }
        return companyDao.listByOrganIds(orgIds, type, childType);
    }

    @Override
    public List<BaseCompany> listCompanyByOrganLevelOne(Integer orgId) {
        return companyDao.listCompanyByOrganLevelOne(orgId);
    }

    @Override
    public List<BaseCompany> listElectricCompanyByOrganLevelOne(Integer orgId) {
        return companyDao.listElectricCompanyByOrganLevelOne(orgId);
    }

    @Override
    public List<BaseCompany> listCompanyByOrganLevelTwo(Integer orgId) {
        return companyDao.listCompanyByOrganLevelTwo(orgId);
    }

    @Override
    public List<BaseCompanyTarget> listCompanyTarget(Integer companyId, Integer cityId) {
        return companyTargetDao.listCompanyTarget(companyId, cityId);
    }

    @Override
    // @CacheEvict(cacheNames = "redis1d", key = "'plat:service:company:types:'+#p0+':plat:'+#p1")
    public List<BaseCompany> listCompanyByTypes(List<CompanyTypeQuery> companyTypeQueryList, Integer plat) {
        return companyDao.listCompanyByTypes(companyTypeQueryList, plat);
    }

    /**
     * 描述: 根据类型，平台标志查询公司信息
     *
     * @param companyTypeQueryList
     *            类型：
     * @param plats
     *            平台标志：1.言而有信 2.啄木鸟,3川南环保
     * @return java.util.List<com.zmn.plat.model.entity.company.BaseCompany>
     * @author wangjie
     * @since 14:50 2019/6/14
     **/
    @Override
    // @CacheEvict(cacheNames = "redis1d", key = "'plat:service:company:types:'+#p0+':plats:'+#p1")
    public List<BaseCompany> listCompanyByTypesAndPlats(List<CompanyTypeQuery> companyTypeQueryList, List<Integer> plats) {

        if (CollectionUtil.isNullOrEmpty(companyTypeQueryList) || CollectionUtil.isNullOrEmpty(plats)) {
            throw new NullPointerException("types is null or plats is null");
        }
        return companyDao.listCompanyByTypesAndPlats(companyTypeQueryList, plats);
    }

    @Override
    public List<BaseCompany> listByQueryForMcc(BaseCompanyQuery query) {
        return companyDao.listByQueryForMcc(query);
    }

    /**
     * 描述: 根据修改时间查询大于该时间状态为禁用的数据
     *
     * @param updateTime
     *            修改时间
     * @param companyTypeQueryList
     *            类型
     * @param plat
     *            平台标志：1.言而有信 2.啄木鸟,3川南环保
     * @return java.util.List<com.zmn.plat.model.entity.company.BaseCompany>
     * @author wangjie
     * @since 17:26 2019/7/11
     **/
    @Override
    public List<BaseCompanyVO> listCompanyByUpdateTime(Date updateTime, List<CompanyTypeQuery> companyTypeQueryList, Integer plat) {
        if (Objects.isNull(updateTime)) {
            throw new NullPointerException("updateTime is null");
        }
        return companyDao.listCompanyByUpdateTime(updateTime, companyTypeQueryList, plat);
    }

    /**
     * 描述:查询搜索服务商
     *
     * @param query
     *            公司查询对象 plat 平台标识，1言而有信，2啄木鸟，3一步维修，4川南环保，Null不限 areaId 大区的组织架构Id，Null不限 companyId 子公司Id，Null不限 type 服务商类型，Null不限 (1,7,9) status
     *            服务商状态，1禁用，2启用，Null不限 keyword 服务商名称，支持中文及拼音模糊搜索，Null不限 java.util.List<com.zmn.common.dto.VtDTO> 服务商公司Id、公司名称和状态字段列表
     * @return java.util.List<com.zmn.plat.model.entity.company.BaseCompany>
     * @author wangjie
     * @since 2019/9/5
     **/
    @Override
    public List<BaseCompany> listManageCompanyVtByQuery(BaseCompanyQuery query) {

        if (Objects.isNull(query)) {
            throw new NullPointerException("query 不能为null");
        }
        return companyDao.listManageCompanyVtByQuery(query);
    }

    @Override
    public List<BaseCompany> listManageCompany(Integer plat, Integer bigAreaId, Integer companyId, Integer type,
                                               Integer childType, Integer status, String keyword) {

        if (NumberUtil.isNullOrZero(bigAreaId) && NumberUtil.isNullOrZero(companyId)) {
            return companyDao.listManageCompanyByNoOrgan(plat, type, childType, status, keyword);
        }

        return companyDao.listManageCompany(plat, bigAreaId, companyId, type, childType, status, keyword);
    }

    @Cacheable(key = "'company:list:plat:'+#p0+'cityId:'+#p2+'companyId:'+#p3", cacheNames =
            "redis1h")
    @Override
    public List<BaseCompany> listByPlatAndCityIdAndCompanyId(Integer plat, Integer cityId, Integer companyId) {

        BaseCompanyQuery query = new BaseCompanyQuery();
        query.setPlat(plat);
        query.setCityId(cityId);
        query.setCompanyId(companyId);
        return companyDao.listByPlatAndCityIdAndCompanyId(query);
    }

    @Cacheable(key = "'company:list:companyTypes:plat:'+#p0", cacheNames = "redis1h")
    @Override
    public List<BaseCompany> listByPlatAndCompanyTypeQuery(Integer plat, List<CompanyTypeQuery> companyTypes) {

        BaseCompanyQuery query = new BaseCompanyQuery();
        query.setCompanyTypeQueryList(companyTypes);
        query.setPlat(plat);
        query.setStatus(GlobalConsts.YES);

        return companyDao.listByPlatAndCityIdAndCompanyId(query);
    }

    @Override
    public Integer countByQuery(BaseCompanyQuery query) {

        return companyDao.countByQuery(query);
    }

    @ZmnDPermit(types = {DPermitTypeEnum.ORG_ONE})
    public Integer countByQueryOfPermitPlat(BaseCompanyQuery query) {

        return companyDao.countByQuery(query);
    }

    @ZmnDPermit(types = {DPermitTypeEnum.ORG_TWO})
    public Integer countByQueryOfPermitRegion(BaseCompanyQuery query) {
        return companyDao.countByQuery(query);
    }

    @ZmnDPermit(types = {DPermitTypeEnum.ORG_THR})
    public Integer countByQueryOfPermitSub(BaseCompanyQuery query) {
        return companyDao.countByQuery(query);
    }

    @ZmnDPermit(types = {DPermitTypeEnum.COMP_SP})
    public Integer countByQueryOfPermitGrandson(BaseCompanyQuery query) {
        return companyDao.countByQuery(query);
    }

    @Override
    // @CacheEvict(cacheNames = "redis1d", key = "'company:id:'+#p0.companyId")
    public Integer updateByKey(BaseCompany company) {
        if (Objects.isNull(company) || NumberUtil.isNullOrZero(company.getCompanyId())) {
            log.error("company or companyId null error", company);
            return 0;
        }

        if (Objects.isNull(company.getUpdateTime())) {
            company.setUpdateTime(DateUtil.getNow());
        }
        if (Objects.isNull(company.getCreateTime())) {
            company.setCreateTime(DateUtil.getNow());
        }

        if (Objects.nonNull(company.getUpdater())) {
            company.setUpdater(company.getUpdater());
        } else {
            company.setUpdater("system");
        }

        return companyDao.updateByKey(company);
    }

    @Override
    public Integer updateByKeySelective(BaseCompany company) {
        if (Objects.isNull(company) || NumberUtil.isNullOrZero(company.getCompanyId())) {
            log.error("company or companyId null error", company);
            return 0;
        }

        if (Objects.isNull(company.getUpdateTime())) {
            company.setUpdateTime(DateUtil.getNow());
        }
        if (Objects.isNull(company.getCreateTime())) {
            company.setCreateTime(DateUtil.getNow());
        }

        if (Objects.nonNull(company.getUpdater())) {
            company.setUpdater(company.getUpdater());
        } else {
            company.setUpdater("system");
        }

        return companyDao.updateByKeySelective(company);
    }

    @SuppressWarnings("Duplicates")
    @Override
    public int updateStatusBatch(List<Integer> arrayIds, int status, String mcStaffName) {
        StatusDTO dto = new StatusDTO();
        dto.setIds(arrayIds);
        dto.setStatus(status);
        dto.setUpdater(mcStaffName);
        dto.setUpdateTime(DateUtil.getNow());

        int relust = companyDao.updateStatusBatch(dto);

        return relust;
    }

    @Override
    public Integer updateSortByKey(BaseCompany company) {
        return companyDao.updateSortByKey(company);
    }

    @Override
    public Integer updateSortByKey(Integer companyId, Integer sort, String mcStaffName) {
        BaseCompany company = new BaseCompany();
        company.setCompanyId(companyId);
        company.setSort(sort);
        company.setUpdater(mcStaffName);
        company.setUpdateTime(DateUtil.getNow());
        return updateSortByKey(company);
    }

    @Override
    // @CacheEvict(cacheNames = "redis1d", key = "'company:all'")
    public Integer insert(BaseCompany company) {
        if (company.getPlat() == null) {
            return GlobalConsts.NONE;
        }

        if (Objects.isNull(company.getUpdateTime())) {
            company.setUpdateTime(DateUtil.getNow());
        }
        if (Objects.isNull(company.getCreateTime())) {
            company.setCreateTime(DateUtil.getNow());
        }

        if (Objects.nonNull(company.getCreater())) {
            company.setUpdater(company.getCreater());
        } else {
            company.setUpdater("system");
            company.setCreater("system");
        }

        int result = companyDao.insert(company);

        companyDao.updateCodeByKey(company.getCompanyId());

        return result;
    }

    @Override
    // @CacheEvict(cacheNames = "redis1d", key = "'company:all'")
    public Integer deleteByKey(Integer companyId) {
        return companyDao.deleteByKey(companyId);
    }

    @Override
    // @CacheEvict(cacheNames = "redis1d", key = "'company:area:all'")
    public void deleteAllCompanyAndAreasCatch() {}

}
